﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using HtmlAgilityPack;

namespace WCrawlerLib.WebSession
{
    public class GoogleTranslate : WebSessionBase, ITranslate
    {
        public string[] UseGoogleTranslation(string paragraph, string hl, string tl)
        {
            string[] result = new string[2];
            string url = string.Format("http://translate.google.com/?langpair={0}|{1}&text={2}#", hl, tl, paragraph.Replace(" ", "+"));
            HtmlDocument doc;
            try
            {
                doc = Get(url);
                //detect language
                string xpath = ".//*[@id='headingtext']";
                Regex r = new Regex(@"(?<language>\w+) to English translation");
                Match m = r.Match(doc.DocumentNode.InnerHtml);
                if (m.Success)
                    result[0] = m.Result("${language}");
                else
                {
                    //Get language cannot tranlate
                    string pattern = @"We are not yet able to translate from (?<language>\w+) into English.";
                    r = new Regex(pattern);
                    m = r.Match(doc.DocumentNode.InnerHtml);
                    if (m.Success)
                    {
                        //Get laguage can translate
                        HtmlNodeCollection nc = doc.DocumentNode.SelectNodes(".//div[@id='spelling-correction']/a/text()");
                        if (nc != null)
                            result[0] = nc[0].InnerHtml;
                        else
                            result[0] = m.Result("${language}");
                    }
                    else
                    {
                        result = TranslateContent(paragraph, paragraph.Length / 2, hl, tl);
                    }
                }

                //Nếu không phải là ngôn ngữ English thì lấy phần translate
                if (!string.IsNullOrEmpty(result[0]) &&
                    string.IsNullOrEmpty(result[1]) && //content is empty or null
                    result[0] != "English")
                {
                    //Get translated content
                    //xpath = @".//*[@id='result_box']";
                    xpath = ".//*[@id='result_box']/span/text()";
                    HtmlNodeCollection nodeColletion = doc.DocumentNode.SelectNodes(xpath);
                    if (nodeColletion != null)
                    {
                        foreach (HtmlNode node in doc.DocumentNode.SelectNodes(xpath))
                            result[1] += node.InnerHtml + " ";
                    }
                }
                else if (result[0] == "English")
                    result[1] = paragraph;
            }
            catch (WebException we)
            {
                throw we;
            }
            catch (Exception ex)
            {
                throw ex;
            }
            return result;
        }

        public string[] TranslateContent(string htmlContent, int lenSplit, string hl, string sl)
        {
            //********************************************
            //Split content into multiple paragraphs
            //********************************************
            int startIndex = 0, endIndex = lenSplit;
            List<string> paragraphs = new List<string>();
            string language = "English";
            while (endIndex < htmlContent.Length && endIndex > 0)
            {
                //Get text contains about 1000 characters
                endIndex = htmlContent.IndexOf(" ", endIndex);
                if (endIndex > 0)
                {
                    paragraphs.Add(htmlContent.Substring(startIndex, endIndex - startIndex));
                    startIndex = endIndex + 1;
                    endIndex += lenSplit;
                }
            }
            paragraphs.Add(htmlContent.Substring(startIndex));

            Object locker = new Object();
            Dictionary<string, string> transContent = new Dictionary<string, string>();
            try
            {
                //Parallel.ForEach<string>(paragraphs, (string text, ParallelLoopState loopState, long index) =>
                Parallel.ForEach<string>(paragraphs, text =>
                {
                    try
                    {
                        string[] result = UseGoogleTranslation(text, hl, sl);
                        lock (locker)
                        {
                            if (!transContent.Keys.Contains(result[1]))
                                transContent.Add(result[1], result[0]);
                        }
                    }
                    catch
                    {

                    }
                }
                );
                //Indentify language exactly
                Dictionary<string, int> countLang = new Dictionary<string, int>();
                int max = 0;
                foreach (KeyValuePair<string, string> lang in transContent)
                {
                    string key = lang.Value;
                    if (countLang.Keys.Contains(key))
                    {
                        countLang[key]++;
                    }
                    else
                        countLang.Add(key, 1);
                    //Get language with max count and priority language isn't English
                    if (countLang[key] > max)
                    {
                        max = countLang[key];
                        if (language != key &&
                            key != "English")
                            language = key;
                    }
                    else
                    {
                        //priority language isn't English indeed it isn't max
                        if (language != key &&
                            language == "English")
                            language = key;
                    }
                }
            }
            catch (WebException we)
            {
                throw we;
            }
            catch (Exception ex)
            {
                throw ex;
            }

            //Get content
            string[] transResult = new string[2];
            transResult[0] = language;
            transResult[1] = string.Join(" ", transContent.ToArray());
            return transResult;
        }
    }
}